﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using CSharp.Libs.Koc;
using System.Collections;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CSharp.Libs.Koc.KernelModels;
using System.Diagnostics;
using System.Collections.ObjectModel;

namespace CSharp.Libs.WPF.UserControls
{
    public class KocInformantControlViewModel : ViewModelBase
    {
        #region declarations
        private Dispatcher _DISP = null;
        private Kernel _KRNL = null;
        private PostHandler _PH = null;
        private WriteDB _wDb = null;

        private Hashtable _htSeed = null;

        private JObject _joSeed = null;

        private ObservableCollection<UserServerCountViewItem> _ocUserServerCounts = new ObservableCollection<UserServerCountViewItem>();
        private UserServerCountViewItem _uscviSelectedItem = new UserServerCountViewItem();

        private ObservableCollection<TblInformationItem> _ocUserServerEntriesDesc = new ObservableCollection<TblInformationItem>();

        private string _strTaxes = "";
        #endregion



        #region constructor / finalizer
        public KocInformantControlViewModel(
            Dispatcher DISP,
            Kernel KRNL)
        {
            _DISP = DISP;
            _KRNL = KRNL;
            _PH = new PostHandler(_KRNL);

            //Instanciate WriteDB class
            if (_wDb == null) { _wDb = new WriteDB(_KRNL); }

            //_getTaxes();

            //subscribe to main seed received event
            _KRNL.SC.SeedReceived += new SeedCollector.SeedReceivedEventHandler(SC_SeedReceived);

            //get counts
            _userServerCountsRefresh();
        }
        #endregion



        #region event handling
        void SC_SeedReceived(object sender, SeedReceivedEventArgs srea)
        {
            try
            {
                //remember Seed
                _htSeed = srea.Seed;

                PlayerItem PI = _createPlayerItem(srea);
                _showData(PI);
                //_getTaxes();

                //Write to db
                if (_wDb.WritePlayerItem(PI))
                {
                    //refresh list
                    _refreshSingleEntry(_wDb.GetUserServerCountByPlayerItem(PI));

                    //refresh this also. just to make sure.
                    _getUserServerEntries();
                }
            }
            catch (Exception ex)
            {
                _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            }
        }
        #endregion



        #region private functions
        /// <summary>
        /// 
        /// </summary>
        /// <param name="srea"></param>
        /// <history>created 18.08.2012</history>
        private PlayerItem _createPlayerItem(
            SeedReceivedEventArgs srea)
        {
            _joSeed = JObject.Parse(srea.SeedText);

            //JSON.net
            if (_joSeed != null)
            {
                //get UserId
                string strUserId = "";
                foreach (JProperty jpSub in _joSeed[constants.KEY_SEED_PLAYERS])
                {
                    strUserId = jpSub.Name.Replace("u", "");
                }

                //init PlayerItem
                PlayerItem PI = new PlayerItem();
                if (srea.FbUId != "") { PI.FbUId = srea.FbUId; }
                PI.ServerId = srea.ServerNr;
                PI.ForeName = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_FNAME].ToString();
                PI.LastName = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_LNAME].ToString();
                PI.PrevTick = Convert.ToInt64(_joSeed["prevtick"].ToString());
                PI.avatarId = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_AVATAR_ID].ToString();
                PI.avatarurl = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_AVATARURL].ToString();
                PI.prefix = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_PREFIX].ToString();
                PI.datejoinUnixTime = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_DATEJOIN_UNIX_TIME].ToString();
                PI.gems = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_GEMS].ToString();
                PI.glory = Convert.ToDouble(_joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_GLORY].ToString());
                PI.maxGlory = Convert.ToDouble(_joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_MAX_GLORY].ToString());
                PI.might = Convert.ToDouble(_joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_MIGHT].ToString());
                PI.name = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_NAME].ToString();
                PI.title = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_TITLE].ToString();
                PI.warStatus = _joSeed[constants.KEY_SEED_PLAYER][constants.KEY_SEED_WAR_STATUS].ToString();
                PI.UserId = strUserId;

                //get city and gold and tax and resource information
                foreach (JArray jaCity in _joSeed[constants.KEY_SEED_CITIES])
                {
                    string strCityId = (string)jaCity[SeedCityData.CityID.GetHashCode()];

                    CityItem CI = new CityItem();
                    CI.CityId = Convert.ToInt64(strCityId);
                    CI.Name = jaCity[SeedCityData.Name.GetHashCode()].ToString();
                    CI.XCoord = Convert.ToInt64(jaCity[SeedCityData.XCoord.GetHashCode()].ToString());
                    CI.YCoord = Convert.ToInt64(jaCity[SeedCityData.YCoord.GetHashCode()].ToString());
                    CI.Gold = Convert.ToInt64(_joSeed[constants.KEY_SEED_CITY_STATS]["city" + strCityId][constants.KEY_SEED_GOLD][SeedGoldData.Gold.GetHashCode()].ToString());
                    CI.Tax = Convert.ToInt64(_joSeed[constants.KEY_SEED_CITY_STATS]["city" + strCityId][constants.KEY_SEED_GOLD][SeedGoldData.Tax.GetHashCode()].ToString());
                    CI.Food = new ResourceItem();
                    //CI.Food.AmountX3600 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Food.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()].ToString());
                    CI.Food.AmountX3600 = Convert.ToInt64(_getValueOfJToken(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Food.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]));
                    CI.Food.Unknown1 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Food.GetHashCode().ToString()][SeedResourceData.Unknown1.GetHashCode()].ToString());
                    CI.Food.Unknown2 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Food.GetHashCode().ToString()][SeedResourceData.Unknown2.GetHashCode()].ToString());
                    CI.Food.Usage = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Food.GetHashCode().ToString()][SeedResourceData.Usage.GetHashCode()].ToString());
                    CI.Wood = new ResourceItem();
                    //CI.Wood.AmountX3600 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Wood.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]);
                    CI.Wood.AmountX3600 = Convert.ToInt64(_getValueOfJToken(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Wood.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]));
                    CI.Wood.Unknown1 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Wood.GetHashCode().ToString()][SeedResourceData.Unknown1.GetHashCode()].ToString());
                    CI.Wood.Unknown2 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Wood.GetHashCode().ToString()][SeedResourceData.Unknown2.GetHashCode()].ToString());
                    CI.Wood.Usage = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Wood.GetHashCode().ToString()][SeedResourceData.Usage.GetHashCode()].ToString());
                    CI.Stone = new ResourceItem();
                    //CI.Stone.AmountX3600 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Stone.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]);
                    CI.Stone.AmountX3600 = Convert.ToInt64(_getValueOfJToken(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Stone.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]));
                    CI.Stone.Unknown1 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Stone.GetHashCode().ToString()][SeedResourceData.Unknown1.GetHashCode()].ToString());
                    CI.Stone.Unknown2 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Stone.GetHashCode().ToString()][SeedResourceData.Unknown2.GetHashCode()].ToString());
                    CI.Stone.Usage = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Stone.GetHashCode().ToString()][SeedResourceData.Usage.GetHashCode()].ToString());
                    CI.Ore = new ResourceItem();
                    //CI.Ore.AmountX3600 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Ore.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]);
                    CI.Ore.AmountX3600 = Convert.ToInt64(_getValueOfJToken(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Ore.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()]));
                    CI.Ore.Unknown1 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Ore.GetHashCode().ToString()][SeedResourceData.Unknown1.GetHashCode()].ToString());
                    CI.Ore.Unknown2 = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Ore.GetHashCode().ToString()][SeedResourceData.Unknown2.GetHashCode()].ToString());
                    CI.Ore.Usage = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Ore.GetHashCode().ToString()][SeedResourceData.Usage.GetHashCode()].ToString());
                    CI.Aetherstone = new ResourceItem();
                    CI.Aetherstone.Amount = Convert.ToInt64(_joSeed[constants.KEY_SEED_RESOURCES]["city" + strCityId]["rec" + ResourceType.Aetherstone.GetHashCode().ToString()][SeedResourceData.AmountX3600.GetHashCode()].ToString());

                    PI.Cities.Add(CI.CityId.ToString(), CI);


                    //Hier unbedingt alle Values über die Funktion _getValueOfJToken holen wie in den Amountx3600 Beispielen

                }

                return PI;
            }

            return null;
        }

        private dynamic _getValueOfJToken(
            JToken jtValue)
        {
            switch (jtValue.Type)
            {
                case JTokenType.Float:
                    return (float)jtValue;

                case JTokenType.Integer:
                    return (Int64)jtValue;

                case JTokenType.String:
                    return jtValue.ToString();
            }

            return jtValue;
        }

        private void _showData(
            PlayerItem PI)
        {
            //prepare sumvars
            Int64 intGold = 0;
            Int64 intFood = 0;
            Int64 intWood = 0;
            Int64 intStone = 0;
            Int64 intOre = 0;
            Int64 intAetherstone = 0;

            //Build sumdata
            foreach (KeyValuePair<string,CityItem> kvpCity in PI.Cities)
            {
                CityItem CI = kvpCity.Value;

                intGold += CI.Gold;
                intFood += CI.Food.Amount;
                intWood += CI.Wood.Amount;
                intStone += CI.Stone.Amount;
                intOre += CI.Ore.Amount;
                intAetherstone += CI.Aetherstone.Amount;
            }

            //Build result
            _strTaxes = String.Concat(_strTaxes,
                PI.UserId,";",
                PI.ServerId, ";",
                PI.PrevTick,";",
                PI.name, ";",
                PI.ForeName, ";",
                PI.LastName, ";",
                intGold, ";",
                intFood.ToString(), ";",
                intWood.ToString(), ";",
                intStone.ToString(), ";",
                intOre.ToString(), ";",
                intAetherstone.ToString(), ";",
                Environment.NewLine);

            
            OnPropertyChanged("Taxes");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  16.08.2012</history>
        private void _getTaxes()
        {
            string strFormat = "{0,-15} {1,3} {2,10} ";
            _strTaxes = string.Format(strFormat, "City", "Tax", "Gold");
            _strTaxes = string.Concat(_strTaxes, Environment.NewLine, 
                "-----------------------------------------------------",
                Environment.NewLine);

            try
            {
                //JSON.net
                //if (_joSeed != null) {

                //    int intPrevTick = (int)_joSeed["prevtick"];
                //    PlayerItem PI = new PlayerItem
                //    {
                //        PrevTick = intPrevTick
                //    };
                //}

                //Hashtable
                if (_htSeed != null &&
                    _htSeed[constants.KEY_SEED_CITY_STATS] != null)
                {
                    Hashtable htCityStats = _htSeed[constants.KEY_SEED_CITY_STATS] as Hashtable;

                    foreach (DictionaryEntry DE in htCityStats)
                    {
                        Hashtable htStats = DE.Value as Hashtable;
                        ArrayList aryGold = htStats[constants.KEY_SEED_GOLD] as ArrayList;

                        _strTaxes = string.Concat(_strTaxes,
                            string.Format(strFormat, DE.Key, aryGold[1].ToString(), aryGold[0].ToString()),
                            Environment.NewLine);
                    }
                }
            }
            catch (Exception ex)
            {
                _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            }

            OnPropertyChanged("Taxes");
        }

        #region user server counts
        /// <summary>
        /// 
        /// </summary>
        /// <history>created  04.09.2012</history>
        private void _userServerCountsRefresh()
        {
            //Clear list
            _userServerCountsClear();

            ArrayList aryUserServerCounts = _wDb.GetUserServerCounts();
            if (aryUserServerCounts != null &&
                aryUserServerCounts.Count > 0)
            {
                foreach (InfoItemBasic iib in aryUserServerCounts)
                {
                    UserServerCountViewItem uscvi = new UserServerCountViewItem
                    {
                        Id = iib.Id,
                        UserId = iib.UserId,
                        ServerId = iib.ServerId,
                        NameInGame = iib.NameInGame,
                        Forename = iib.Forename,
                        Lastname = iib.Lastname,
                        Count = iib.Count,
                    };
                    _userServerCountsAdd(uscvi);
                }
            }

            OnPropertyChanged("UserServerCounts");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uscvi"></param>
        /// <history>created  04.09.2012</history>
        private void _userServerCountsAdd(
            UserServerCountViewItem uscvi)
        {
            _DISP.Invoke((Action)delegate
            {
                _ocUserServerCounts.Add(uscvi);
                OnPropertyChanged("UserServerCounts");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  04.09.2012</history>
        private void _userServerCountsClear()
        {
            _DISP.Invoke((Action)delegate
            {
                _ocUserServerCounts.Clear();
                OnPropertyChanged("UserServerCounts");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iib"></param>
        /// <history>created  06.09.2012</history>
        private void _refreshSingleEntry(
            InfoItemBasic iib)
        {
            //exist switch
            bool fEntryExists = false;

            //cycle through Collection
            foreach (UserServerCountViewItem uscvi in _ocUserServerCounts)
            {
                //if entry was found, refresh view item
                if (uscvi.UserId == iib.UserId &&
                    uscvi.ServerId == iib.ServerId)
                {
                    uscvi.Count = iib.Count;
                    fEntryExists = true;
                    break;
                }
            }

            //if nothing was found, do a complete refresh
            if (!fEntryExists) { _userServerCountsRefresh(); }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  11.09.2012</history>
        private void _getUserServerEntries()
        {
            if (_uscviSelectedItem != null &&
                _uscviSelectedItem.UserId > 0 &&
                _uscviSelectedItem.ServerId > 0)
            {
                IList<TblInformationItem> lstInformations = _wDb.GetInformationsByUserServer(_uscviSelectedItem.UserId, _uscviSelectedItem.ServerId);

                if (lstInformations != null &&
                    lstInformations.Count > 0)
                {
                    _ocUserServerEntriesDesc = new ObservableCollection<TblInformationItem>(lstInformations);
                }
            }
        }
        #endregion
        #endregion



        #region interface
        #region properties
        public string Taxes { get { return _strTaxes; } set { _strTaxes = ""; OnPropertyChanged("Taxes"); } }

        public ObservableCollection<UserServerCountViewItem> UserServerCounts { get { return _ocUserServerCounts; } set { _ocUserServerCounts = value; OnPropertyChanged("UserServerCounts"); } }
        public UserServerCountViewItem SelectedCountItem
        {
            get { return _uscviSelectedItem; }
            set
            {
                _uscviSelectedItem = value;
                OnPropertyChanged("SelectedCountItem");
                _getUserServerEntries();
                OnPropertyChanged("UserServerEntriesDesc");
            }
        }

        public ObservableCollection<TblInformationItem> UserServerEntriesDesc { get { return _ocUserServerEntriesDesc; } set { _ocUserServerEntriesDesc = value; OnPropertyChanged("UserServerEntriesDesc"); } }
        #endregion

        #region methods
        /// <summary>
        /// 
        /// </summary>
        /// <history>created  04.09.2012</history>
        public void UserServerCountsRefresh()
        {
            _userServerCountsRefresh();
        }
        #endregion
        #endregion
    }
}
